package arsmodeller.model.impl;

import java.util.Collection;

import org.eclipse.draw2d.geometry.Point;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.impl.EObjectImpl;
import org.eclipse.emf.ecore.util.EDataTypeUniqueEList;
import org.eclipse.emf.ecore.util.EcoreUtil;

import arsmodeller.model.Link;
import arsmodeller.model.ObjectProcessingDiagram;
import arsmodeller.model.Package;
import arsmodeller.model.Thing;

public class LinkImpl extends EObjectImpl implements Link {
	protected Thing source;

	/**
	 * The cached value of the '{@link #getTarget() <em>Target</em>}' reference.
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @see #getTarget()
	 * @generated
	 * @ordered
	 */
	protected Thing target;

	/**
	 * The cached value of the '{@link #getBendpoints() <em>Bendpoints</em>}'
	 * attribute list. <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @see #getBendpoints()
	 * @generated
	 * @ordered
	 */
	protected EList<Point> bendpoints;

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	protected LinkImpl() {
		super();
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	@Override
	protected EClass eStaticClass() {
		return Package.Literals.OPM_LINK;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public ObjectProcessingDiagram getOpd() {
		if (eContainerFeatureID() != Package.OPM_LINK__OPD)
			return null;
		return (ObjectProcessingDiagram) eContainer();
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public NotificationChain basicSetOpd(ObjectProcessingDiagram newOpd,
			NotificationChain msgs) {
		msgs = eBasicSetContainer((InternalEObject) newOpd,
				Package.OPM_LINK__OPD, msgs);
		return msgs;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public void setOpd(ObjectProcessingDiagram newOpd) {
		if (newOpd != eInternalContainer()
				|| (eContainerFeatureID() != Package.OPM_LINK__OPD && newOpd != null)) {
			if (EcoreUtil.isAncestor(this, newOpd))
				throw new IllegalArgumentException(
						"Recursive containment not allowed for " + toString());
			NotificationChain msgs = null;
			if (eInternalContainer() != null)
				msgs = eBasicRemoveFromContainer(msgs);
			if (newOpd != null)
				msgs = ((InternalEObject) newOpd).eInverseAdd(this,
						Package.OPM_OBJECT_PROCESS_DIAGRAM__LINKS,
						ObjectProcessingDiagram.class, msgs);
			msgs = basicSetOpd(newOpd, msgs);
			if (msgs != null)
				msgs.dispatch();
		} else if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET,
					Package.OPM_LINK__OPD, newOpd, newOpd));
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public Thing getSource() {
		if (source != null && source.eIsProxy()) {
			InternalEObject oldSource = (InternalEObject) source;
			source = (Thing) eResolveProxy(oldSource);
			if (source != oldSource) {
				if (eNotificationRequired())
					eNotify(new ENotificationImpl(this, Notification.RESOLVE,
							Package.OPM_LINK__SOURCE, oldSource, source));
			}
		}
		return source;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public Thing basicGetSource() {
		return source;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public NotificationChain basicSetSource(Thing newSource,
			NotificationChain msgs) {
		Thing oldSource = source;
		source = newSource;
		if (eNotificationRequired()) {
			ENotificationImpl notification = new ENotificationImpl(this,
					Notification.SET, Package.OPM_LINK__SOURCE, oldSource,
					newSource);
			if (msgs == null)
				msgs = notification;
			else
				msgs.add(notification);
		}
		return msgs;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public void setSource(Thing newSource) {
		if (newSource != source) {
			NotificationChain msgs = null;
			if (source != null)
				msgs = ((InternalEObject) source)
						.eInverseRemove(this,
								Package.OPM_THING__OUTGOING_LINKS,
								Thing.class, msgs);
			if (newSource != null)
				msgs = ((InternalEObject) newSource)
						.eInverseAdd(this,
								Package.OPM_THING__OUTGOING_LINKS,
								Thing.class, msgs);
			msgs = basicSetSource(newSource, msgs);
			if (msgs != null)
				msgs.dispatch();
		} else if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET,
					Package.OPM_LINK__SOURCE, newSource, newSource));
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public Thing getTarget() {
		if (target != null && target.eIsProxy()) {
			InternalEObject oldTarget = (InternalEObject) target;
			target = (Thing) eResolveProxy(oldTarget);
			if (target != oldTarget) {
				if (eNotificationRequired())
					eNotify(new ENotificationImpl(this, Notification.RESOLVE,
							Package.OPM_LINK__TARGET, oldTarget, target));
			}
		}
		return target;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public Thing basicGetTarget() {
		return target;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public NotificationChain basicSetTarget(Thing newTarget,
			NotificationChain msgs) {
		Thing oldTarget = target;
		target = newTarget;
		if (eNotificationRequired()) {
			ENotificationImpl notification = new ENotificationImpl(this,
					Notification.SET, Package.OPM_LINK__TARGET, oldTarget,
					newTarget);
			if (msgs == null)
				msgs = notification;
			else
				msgs.add(notification);
		}
		return msgs;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public void setTarget(Thing newTarget) {
		if (newTarget != target) {
			NotificationChain msgs = null;
			if (target != null)
				msgs = ((InternalEObject) target)
						.eInverseRemove(this,
								Package.OPM_THING__INCOMING_LINKS,
								Thing.class, msgs);
			if (newTarget != null)
				msgs = ((InternalEObject) newTarget)
						.eInverseAdd(this,
								Package.OPM_THING__INCOMING_LINKS,
								Thing.class, msgs);
			msgs = basicSetTarget(newTarget, msgs);
			if (msgs != null)
				msgs.dispatch();
		} else if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET,
					Package.OPM_LINK__TARGET, newTarget, newTarget));
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	public EList<Point> getBendpoints() {
		if (bendpoints == null) {
			bendpoints = new EDataTypeUniqueEList<Point>(Point.class, this,
					Package.OPM_LINK__BENDPOINTS);
		}
		return bendpoints;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	@Override
	public NotificationChain eInverseAdd(InternalEObject otherEnd,
			int featureID, NotificationChain msgs) {
		switch (featureID) {
		case Package.OPM_LINK__OPD:
			if (eInternalContainer() != null)
				msgs = eBasicRemoveFromContainer(msgs);
			return basicSetOpd((ObjectProcessingDiagram) otherEnd, msgs);
		case Package.OPM_LINK__SOURCE:
			if (source != null)
				msgs = ((InternalEObject) source)
						.eInverseRemove(this,
								Package.OPM_THING__OUTGOING_LINKS,
								Thing.class, msgs);
			return basicSetSource((Thing) otherEnd, msgs);
		case Package.OPM_LINK__TARGET:
			if (target != null)
				msgs = ((InternalEObject) target)
						.eInverseRemove(this,
								Package.OPM_THING__INCOMING_LINKS,
								Thing.class, msgs);
			return basicSetTarget((Thing) otherEnd, msgs);
		}
		return super.eInverseAdd(otherEnd, featureID, msgs);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	@Override
	public NotificationChain eInverseRemove(InternalEObject otherEnd,
			int featureID, NotificationChain msgs) {
		switch (featureID) {
		case Package.OPM_LINK__OPD:
			return basicSetOpd(null, msgs);
		case Package.OPM_LINK__SOURCE:
			return basicSetSource(null, msgs);
		case Package.OPM_LINK__TARGET:
			return basicSetTarget(null, msgs);
		}
		return super.eInverseRemove(otherEnd, featureID, msgs);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	@Override
	public NotificationChain eBasicRemoveFromContainerFeature(
			NotificationChain msgs) {
		switch (eContainerFeatureID()) {
		case Package.OPM_LINK__OPD:
			return eInternalContainer().eInverseRemove(this,
					Package.OPM_OBJECT_PROCESS_DIAGRAM__LINKS,
					ObjectProcessingDiagram.class, msgs);
		}
		return super.eBasicRemoveFromContainerFeature(msgs);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	@Override
	public Object eGet(int featureID, boolean resolve, boolean coreType) {
		switch (featureID) {
		case Package.OPM_LINK__OPD:
			return getOpd();
		case Package.OPM_LINK__SOURCE:
			if (resolve)
				return getSource();
			return basicGetSource();
		case Package.OPM_LINK__TARGET:
			if (resolve)
				return getTarget();
			return basicGetTarget();
		case Package.OPM_LINK__BENDPOINTS:
			return getBendpoints();
		}
		return super.eGet(featureID, resolve, coreType);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	@SuppressWarnings("unchecked")
	@Override
	public void eSet(int featureID, Object newValue) {
		switch (featureID) {
		case Package.OPM_LINK__OPD:
			setOpd((ObjectProcessingDiagram) newValue);
			return;
		case Package.OPM_LINK__SOURCE:
			setSource((Thing) newValue);
			return;
		case Package.OPM_LINK__TARGET:
			setTarget((Thing) newValue);
			return;
		case Package.OPM_LINK__BENDPOINTS:
			getBendpoints().clear();
			getBendpoints().addAll((Collection<? extends Point>) newValue);
			return;
		}
		super.eSet(featureID, newValue);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	@Override
	public void eUnset(int featureID) {
		switch (featureID) {
		case Package.OPM_LINK__OPD:
			setOpd((ObjectProcessingDiagram) null);
			return;
		case Package.OPM_LINK__SOURCE:
			setSource((Thing) null);
			return;
		case Package.OPM_LINK__TARGET:
			setTarget((Thing) null);
			return;
		case Package.OPM_LINK__BENDPOINTS:
			getBendpoints().clear();
			return;
		}
		super.eUnset(featureID);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	@Override
	public boolean eIsSet(int featureID) {
		switch (featureID) {
		case Package.OPM_LINK__OPD:
			return getOpd() != null;
		case Package.OPM_LINK__SOURCE:
			return source != null;
		case Package.OPM_LINK__TARGET:
			return target != null;
		case Package.OPM_LINK__BENDPOINTS:
			return bendpoints != null && !bendpoints.isEmpty();
		}
		return super.eIsSet(featureID);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated
	 */
	@Override
	public String toString() {
		if (eIsProxy())
			return super.toString();

		StringBuffer result = new StringBuffer(super.toString());
		result.append(" (bendpoints: ");
		result.append(bendpoints);
		result.append(')');
		return result.toString();
	}
}
